﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using fastJSON;

namespace GameSeed.Communication.Client
{
    public class SocketClient
    {
        #region 内部
        
        private Socket socket;
        private string ip;
        private int port;
        private CommandManager commandManager = new CommandManager();

        private string receiveCache = string.Empty;
        private Thread innerThread;

        private void connect()
        {
            IPAddress ipAddress = IPAddress.Parse(ip);
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Connect(ipAddress, port);
        }

        private void send(string data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            socket.Send(byteData);
        }

        private void receive()
        {
            innerThread = new Thread(receiveCore);
            innerThread.Start();
        }

        private void receiveCore()
        {
            while (true)
            {
                try
                {
                    //创建一个字节数组接收数据
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
                    //接收数据
                    int length = socket.Receive(arrMsgRec);
                    //将字节数组转换成字符串,此时是将所有的元素都转成字符串了，而真正接收到的只有服务端发来的几个字符。
                    receiveCache += System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);

                    reciveData();

                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    //结束当前线程
                    //Thread.CurrentThread.Abort();
                }
            }
        }

        private void reciveData()
        {
            var result = receiveCache.IndexOf("\r\n");
            while (result != -1)
            {
                string text = receiveCache.Substring(0, result);
                receiveCache = receiveCache.Substring(result + 2, receiveCache.Length - result - 2);
                excuteCommand(text);

                result = receiveCache.IndexOf("\r\n");
            }
        }

        private void excuteCommand(string text)
        {
            commandManager.Excute(text);
        }

        #endregion

        #region 公开

        public SocketClient(string ip, int port)
        {
            this.ip = ip;
            this.port = port;
            connect();

            receive();
        }

        public void Reconnect()
        {
            connect();

            receive();
        }
        
        public void Command(string command)
        {
            Command(command, string.Empty);
        }

        public void Command(string command, object data)
        {
            Command(command, JSON.Instance.ToJSON(data));
        }

        public void Command(string command, string data)
        {
            if (!socket.Connected)
                connect();

            send(string.Format("{0} {1}\r\n", command, data));
        }

        public void Close()
        {
            if (socket.Connected)
                socket.Shutdown(SocketShutdown.Both);

            if (innerThread != null)
            {
                innerThread.Interrupt();
                innerThread = null;
            }
        }

        public void RegistCommand(string command, CommandHandler handler)
        {
            commandManager.RegistCommand(command, handler);
        }

        public void ClearCommand(string command)
        {
            commandManager.ClearCommand(command);
        }

        #endregion
    }
}
